/*
 * 描述： <描述>
 * 修改人： rain
 * 修改时间： 2016年8月9日
 * 项目： rainhy-config
 */
package com.rainhy.config.propertiesloader;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.apache.commons.collections.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import com.rainhy.config.config.ConfigProperty;
import com.rainhy.config.context.ConfigContext;
import com.rainhy.core.util.AssertUtils;

/**
 * ConfigContext配置占位符注入器<br>
 * 用来把ConfigContext读取的配置注入到spring的配置信息里面<br>
 * 这里要特别注意:如果在[ConfigContext的配置管理器]里面有注入 springbean 那么此springbean就不能使用ConfigContext注入的配置.不然会造成循环依赖<br>
 * 注意:在同时使用多个PropertyPlaceholderConfigurer时,必须跳过占位符解析异常,请设置所有PropertyPlaceholderConfigurer的参数ignoreUnresolvablePlaceholders=true<br>
 * 可以在代码里面使用注解 @Value(${xxx}) 来获取值
 * 
 * @author rain
 * @version [版本号, 2016年8月9日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class ConfigContextInjectSpringPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    
    public ConfigContextInjectSpringPlaceholderConfigurer() {
        this.ignoreUnresolvablePlaceholders = true;
    }
    
    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
        ConfigContext configContext = beanFactoryToProcess.getBean(ConfigContext.class);
        if (configContext != null) {
            Map<String, ConfigProperty> configPropertyMap = configContext.getAllConfigPropertyMap();
            if (MapUtils.isNotEmpty(configPropertyMap)) {
                for (Entry<String, ConfigProperty> entryTemp : configPropertyMap.entrySet()) {
                    String key = entryTemp.getKey();
                    AssertUtils.notContains(props, key, "ConfigContext注入的配置信息与Property配置信息 key 值重复. key = {}", key);
                    props.setProperty(key, entryTemp.getValue().getValue());
                }
            }
            super.processProperties(beanFactoryToProcess, props);
        }
    }
}
